#!/bin/sh

set -e

### Helper functions

# For whatever reason, the initscript that calls us sets a pretty scarse $PATH
PATH="/usr/bin:${PATH}"

### Helper functions

using_fromiso() {
	grep -qs -w -E '(fromiso|isofrom)=' /proc/cmdline
}

# Returns the boot device's path in a form that can be passed to the
# eject command, e.g. /dev/scd0 or /dev/block/NN:MM.
boot_device() {
	if using_fromiso ; then
	# When booting with e.g. fromiso=/dev/sdx3/tails-XXX.iso, a loop device
	# is mounted onto /lib/live/mount/medium => we cannot get the boot device from there.
	# This loop device's backing file is seen by the system as
	# /isofrom/XXX.iso, which is not available presumably because pivotroot
	# was run => we cannot get the boot device from there either.
	# Instead, we parse fromiso='s argument the same way live-boot does
	# in order to extract the device path (/dev/sdx3)
		for ARGUMENT in $(cat /proc/cmdline) ; do
			case "${ARGUMENT}" in
				isofrom=*|fromiso=*)
					FROMISO="${ARGUMENT#*=}"
					;;
			esac
		done
		echo $(dirname "$FROMISO")
	else
	# Refactorer, beware: the rest of this script depends on the fact that
	# the path returned in this case is suitable to be passed as an argument
	# to --path in "udevadm info --query" commands... which is not the case
	# of paths in the /dev/sdxN form.
		DEV_NUMBER="$(udevadm info --device-id-of-file=/lib/live/mount/medium)"
		echo "/dev/block/$DEV_NUMBER"
	fi
}

# First clean the screen, then brutally shutdown the machine.
do_stop() {
	# Really make sure that the CD is ejected
	# FIXME: this might not be necessary with future kernel/udev
	if [ "${DEV_TYPE}" = "cd" ]; then
		/usr/bin/eject -i off "${BOOT_DEVICE}" || true
		/usr/bin/eject -m "${BOOT_DEVICE}" || true
	fi

	/usr/bin/pkill gdm3 || true
	/etc/init.d/kexec-load stop  || true
	/lib/systemd/system-shutdown/tails-kexec || true
}


### Main

BOOT_DEVICE=$(boot_device)

# Assign to QUERY_SELECTOR an option that can be passed as a query selector
# to udevadm info --query commands.
if using_fromiso ; then
	DEV_NAME=$(basename "$BOOT_DEVICE")
	QUERY_SELECTOR="--name $DEV_NAME"
else
	QUERY_SELECTOR="--path $BOOT_DEVICE"
fi

DEV_UDEV_PATH=$(udevadm info --query path     $QUERY_SELECTOR)
# SD in SDIO has no ID_TYPE, let's pretend it's a disk just like USB sticks
DEV_TYPE_LINE=$(udevadm info --query property $QUERY_SELECTOR | grep -w '^ID_TYPE') \
	|| DEV_TYPE_LINE='ID_TYPE=disk'
DEV_TYPE="${DEV_TYPE_LINE#*=}"

# If the world was sane we'd want to *disable* the eject lock, but it turns out
# that blocks the block events so udev-watchdog never receives the "change"
# event. See [[bugs/sdmem_on_eject_broken_for_CD]].
# FIXME: we might be able to do the more sane "-i off" with future kernel/udev
if [ "$DEV_TYPE" = "cd" ]; then
	eject -i on "${BOOT_DEVICE}" >/dev/null
fi

# Start udev-watchdog and stop on clean exit.
/usr/local/sbin/udev-watchdog "$DEV_UDEV_PATH" "$DEV_TYPE" && do_stop
